package com.android.stockme.frontend;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.android.stockme.backend.BackendController;
import com.android.stockme.backend.IBackendController;
import com.android.stockme.backend.ITickListener;
import com.android.stockme.backend.configuration.IConfigurationManager;
import com.android.stockme.backend.portfolio.IStockData;
import com.android.stockme.backend.portfolio.IStockPortfolioUpdatedListener;
import com.android.stockme.backend.util.Tupple;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.KeyEvent.Callback;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;

public class StockMePortfolioTab extends ListActivity implements OnClickListener, Callback {

	/** 
	 * @uml.property name="portfolioAdapter"
	 * @uml.associationEnd multiplicity="(1 1)" inverse="stockMePortfolioTab:com.android.stockme.frontend.PortfolioAdapter"
	 */
	private PortfolioAdapter portfolioAdapter = null;
	private StockMePortfolioTab instance = null;
	private IBackendController backend = null;
	private ToneGenerator toneGenerator = null;
	
	private Button addButton = null;
	private EditText symbolEntryTextField = null;
	
	private int currentSelectedIndex = 0;
	
	private ArrayList<IStockData> stocks = null;
	
	private Dialog stockDetailsDialog = null;
	private TextView currentTxt = null;
	private TextView changeTxt = null;
	private EditText highBoundEdt = null;
	private EditText lowBoundEdt = null;
	private CheckBox highBoundChBox = null;
	private CheckBox lowBoundChBox = null;
	private GraphView stockValueGraph = null;
	private Button deleteBtn = null;
	private Button applyBtn = null;
	private Button closeBtn = null;
	
	private AlarmDialogAdapter alarmAdapter = null;
	private Dialog alarmDialog = null;
	private ListView alarmListView = null;
	private Button okButton = null;
	
	public void onClick(View v) {
		if (v.getParent() instanceof RelativeLayout) {
			RelativeLayout rl = (RelativeLayout)v.getParent();
			this.onListItemClick(getListView(), rl, rl.getId(), rl.getId());
		}
		else if (v instanceof RelativeLayout) {
			this.onListItemClick(getListView(), v, v.getId(), v.getId());
		}
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		this.setContentView(R.layout.portfolio);
		this.getListView().setEmptyView(findViewById(R.id.empty));
	
		this.instance = this;
		this.backend = BackendController.getBackendController();
		this.stocks = this.backend.getStockPortfolio().getStocks();
		this.portfolioAdapter = new PortfolioAdapter(this.backend, this, this);
		this.setListAdapter(this.portfolioAdapter);
		this.toneGenerator = new ToneGenerator(AudioManager.STREAM_ALARM, ToneGenerator.MAX_VOLUME);
		
		this.addButton = (Button)findViewById(R.id.add_symbols_button);
		this.addButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				addStock(v);
			}
		});
		
		this.symbolEntryTextField = (EditText)findViewById(R.id.stock_symbols);
		this.symbolEntryTextField.setOnKeyListener(new OnKeyListener() {
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if (keyCode == KeyEvent.KEYCODE_ENTER) {
					addStock(v);
					return true;
				}
				return false;
			}			
		});
				
		this.backend.getStockPortfolio().registerStockPortfolioUpdatedListener(new IStockPortfolioUpdatedListener() {
			public void notifyStockPortfolioUpdated(Object arg) {
				stocks = backend.getStockPortfolio().getStocks();
			}			
		});
		
		this.backend.registerStockTickListener(new ITickListener() {
			public void notifyTick(Object arg) {
				if (!backend.getConfigurationManager().getNotificationState())
					return;

				
				if (alarmDialog == null) {
					createAlarmDialog(new ArrayList<String>((Collection<String>)arg));
					alarmAdapter.notifyDataSetChanged();
				}
				else
					alarmAdapter.setData(new ArrayList<String>((Collection<String>)arg));

				if (alarmAdapter.getCount() > 0) {
					toneGenerator.startTone(ToneGenerator.TONE_PROP_BEEP);
					alarmDialog.show();
					toneGenerator.stopTone();
				}
			}			
		});
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);

		this.currentSelectedIndex = position;
		
		this.showStockDetailsDialog(l, v);
	}

	private void showStockDetailsDialog(ListView l, View v) {
		if (this.stockDetailsDialog == null)
			this.createStockDetailsDialog();

		if (this.currentSelectedIndex < 0)
			return;
		
		IConfigurationManager configuration = this.backend.getConfigurationManager();
		IStockData stockData = (IStockData)this.portfolioAdapter.getItem(this.currentSelectedIndex);
		
		this.stockDetailsDialog.setTitle(stockData.getSymbol());

		if(stockData.getRelativeChange() < 0)
			this.changeTxt.setTextColor(0xffb22222);	
		else
			this.changeTxt.setTextColor(0xff2e8b57);

		this.changeTxt.setText(Float.toString(stockData.getRelativeChange()) + "%");
		this.currentTxt.setText(Float.toString(stockData.getValue()));
		this.highBoundEdt.setText(Float.toString(configuration.getHighBound(stockData.getSymbol())));
		this.lowBoundEdt.setText(Float.toString(configuration.getLowBound(stockData.getSymbol())));
		this.highBoundChBox.setChecked(configuration.isHighBoundConfigured(stockData.getSymbol()));
		this.lowBoundChBox.setChecked(configuration.isLowBoundConfigured(stockData.getSymbol()));

		this.highBoundEdt.setEnabled(this.highBoundChBox.isChecked());
		this.lowBoundEdt.setEnabled(this.lowBoundChBox.isChecked());

		this.createGraphView();

		this.stockDetailsDialog.show();
	}
	
	private void createStockDetailsDialog() {
		stockDetailsDialog = new Dialog(instance);
		stockDetailsDialog.setContentView(R.layout.stock_details_partial2);
		deleteBtn = (Button)stockDetailsDialog.findViewById(R.id.delete_button);
		deleteBtn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				stockDetailsDialog.dismiss();
				removeStock(v);
			}
		});
		applyBtn = (Button)stockDetailsDialog.findViewById(R.id.apply_button);
		applyBtn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if (setStockConfiguration())
					stockDetailsDialog.dismiss();
			}			
		});
		closeBtn = (Button)stockDetailsDialog.findViewById(R.id.close_button);
		closeBtn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				stockDetailsDialog.dismiss();
			}			
		});
		currentTxt = (TextView)stockDetailsDialog.findViewById(R.id.current);
		changeTxt = (TextView)stockDetailsDialog.findViewById(R.id.change);
		highBoundEdt = (EditText)stockDetailsDialog.findViewById(R.id.high_bound_edt);
		lowBoundEdt = (EditText)stockDetailsDialog.findViewById(R.id.low_bound_edt);
		highBoundChBox = (CheckBox)stockDetailsDialog.findViewById(R.id.high_bound_chbox);
		lowBoundChBox = (CheckBox)stockDetailsDialog.findViewById(R.id.low_bound_chbox);
		
		highBoundChBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				highBoundEdt.setEnabled(isChecked);
			}
		});
		lowBoundChBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				lowBoundEdt.setEnabled(isChecked);
			}
		});
//		this.stockValueGraph = new GraphView(this, null, "Stock Values", null, null, GraphView.LINE);
		this.stockValueGraph = (GraphView)stockDetailsDialog.findViewById(R.id.stock_val_graph);
	}

	private void createGraphView() {
		IStockData stockData = (IStockData)this.portfolioAdapter.getItem(this.currentSelectedIndex);
		List<Tupple<String, Float>> graphData = this.backend.fetchStockHistory(stockData.getSymbol());
		
		if (graphData == null || graphData.size() == 0) {
			this.createEmptyGraph();
			return;
		}
		
		float values[] = new float[graphData.size()];
		String horLabels[] = { graphData.get(graphData.size() - 1).getT1(), graphData.get(0).getT1() };	
		String verLabels[] = new String[graphData.size()];
//		String horLabels[] = new String[graphData.size()];		
		int index = graphData.size() - 1;
//		int index = 0;
		
		for(Tupple<String, Float> t : graphData) {
			values[index] = t.getT2();
			verLabels[index] = Float.toString(t.getT2());
//			horLabels[index] = t.getT1();
			index--;
//			index++;
		}
		Arrays.sort(verLabels);
		this.stockValueGraph.setData(values, "Stock Values", horLabels, new String[] { verLabels[graphData.size() - 1], verLabels[0] }, GraphView.LINE);		
	}
	
	private void createEmptyGraph() {
		this.stockValueGraph.setData(new float[0], "No values found", null, null, GraphView.LINE);				
	}
	
	private boolean setStockConfiguration() {
		
		if (!this.validateConfiguration())
			return false;
		
		IConfigurationManager configuration = this.backend.getConfigurationManager();
		
		IStockData stockData = (IStockData)this.portfolioAdapter.getItem(this.currentSelectedIndex);
		
		configuration.setHighBound(stockData.getSymbol(), Float.parseFloat(this.highBoundEdt.getText().toString()));
		configuration.setLowBound(stockData.getSymbol(), Float.parseFloat(this.lowBoundEdt.getText().toString()));
		configuration.setHighEnableDisable(stockData.getSymbol(), this.highBoundChBox.isChecked());
		configuration.setLowEnableDisable(stockData.getSymbol(), this.lowBoundChBox.isChecked());
		
		return true;
	}

	private boolean validateConfiguration() {

		float highBound = Float.parseFloat(this.highBoundEdt.getText().toString());
		float lowBound = Float.parseFloat(this.lowBoundEdt.getText().toString());
		
		if (this.highBoundChBox.isChecked() && this.lowBoundChBox.isChecked() && highBound < lowBound) {
			AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this.instance);
			dialogBuilder.setCancelable(false);
			dialogBuilder.setTitle("Error");
			dialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
			dialogBuilder.setMessage("Lower bound must be smaller or equal than higher bound!");
			dialogBuilder.create().show();		
			
			return false;
		}
		
		return true;
	}
	
	private void addStock(View v) {
		String symbolsStr = symbolEntryTextField.getText().toString();
		symbolsStr = symbolsStr.replace("\n", " ");
		String symbolArray[] = symbolsStr.split(" ");

		for (String s : symbolArray)
			if (s != "" && !Character.isWhitespace(s.charAt(0)))
				this.backend.getConfigurationManager().addStock(s.toUpperCase());

		symbolEntryTextField.setText(null);
	}
	
	private void removeStock(View v) {
		this.backend.getConfigurationManager().removeStock(this.stocks.get(this.currentSelectedIndex).getSymbol());
	}

	private void createAlarmDialog(ArrayList<String> adapterData) {
		this.alarmDialog = new Dialog(this);
		this.alarmDialog.setContentView(R.layout.alaram_dialog);
		this.alarmDialog.setTitle("Stocks Portfolio Updated!");
		
		this.okButton = (Button)this.alarmDialog.findViewById(R.id.alarm_dialog_ok_button);
		this.okButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				alarmDialog.dismiss();
			}
		});
		
		this.alarmListView = (ListView)this.alarmDialog.findViewById(R.id.alarm_list_view);
		this.alarmAdapter = new AlarmDialogAdapter(this.backend, this, adapterData);
		this.alarmListView.setAdapter(this.alarmAdapter);
	}
	
	private void setAlarmSelectedItem(String symbol) {
		this.currentSelectedIndex = this.portfolioAdapter.getItem(symbol);
	}
	
	private class AlarmDialogAdapter extends BaseAdapter implements ListAdapter, OnClickListener {

		private IBackendController backend = null;
		private Context context = null;
		private ArrayList<String> alarmStmbols = null;

		public AlarmDialogAdapter(IBackendController backend, Context context, ArrayList<String> data) {
			this.backend = backend;
			this.context = context;
			this.alarmStmbols = data;
		}
		
		public int getCount() {
			return this.alarmStmbols.size();
		}

		public Object getItem(int position) {
			return this.alarmStmbols.get(position);
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			LayoutInflater inflater = LayoutInflater.from(this.context);
			RelativeLayout cellLayout = (RelativeLayout)inflater.inflate(R.layout.alarm_dialog_node, null);
			cellLayout.setMinimumWidth(parent.getWidth());
			int color;
			
			String symbol = this.alarmStmbols.get(position);
			IStockData stock = this.backend.getStockPortfolio().getStockData(symbol);

			if(position % 2 > 0)
				color = Color.rgb(48,92,131);
			else 
				color = Color.rgb(119,138,170);
			cellLayout.setBackgroundColor(color);
			
			TextView field = (TextView)cellLayout.findViewById(R.id.alarm_node_symbol);
			field.setBackgroundColor(color);
			field.setText(stock.getSymbol());
			field.setClickable(true);
			field.setOnClickListener(this);

			field = (TextView)cellLayout.findViewById(R.id.alarm_node_current);
			field.setText(Float.toString(stock.getValue()));
			field.setClickable(true);
			field.setOnClickListener(this);

			field = (TextView)cellLayout.findViewById(R.id.alarm_node_change);
			field.setClickable(true);
			field.setOnClickListener(this);
			
			String change = ((stock.getRelativeChange() < 0) ? Float.toString(stock.getRelativeChange()) : ("+" + Float.toString(stock.getRelativeChange())));

			if (stock.isExists() == false) {
				field.setBackgroundColor(0x00000000);
			}
			else {
				if(stock.getRelativeChange() >= 0)
					field.setBackgroundColor(0xff2e8b57);
				else
					field.setBackgroundColor(0xffb22222);
			}
			
			field.setText(change);

			cellLayout.setId(position);
			cellLayout.setClickable(true);
			cellLayout.setOnClickListener(this);
			return cellLayout;
		}
	
		public void setData(ArrayList<String> alarmStmbols) {
			this.alarmStmbols = alarmStmbols;
			this.notifyDataSetChanged();
		}

		public void onClick(View v) {
			if (v.getParent() instanceof RelativeLayout) {
				RelativeLayout rl = (RelativeLayout)v.getParent();
				setAlarmSelectedItem((String)this.getItem(rl.getId()));
				showStockDetailsDialog(getListView(), rl);
				this.alarmStmbols.remove(rl.getId());
			}
			else if (v instanceof RelativeLayout) {
				setAlarmSelectedItem((String)this.getItem(v.getId()));
				showStockDetailsDialog(getListView(), v);
				this.alarmStmbols.remove(v.getId());
			}
			this.notifyDataSetChanged();
		}
	}
}
